﻿using System;

using System.Text;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;

namespace HDJ.Framework.Core
{
    /// <summary>从字符串中识别出大数</summary>
    class IdentifyNumber
    {

        /// <summary>识别出一个大数，返回值为这个是不是正数</summary> 
        public static bool GetBigNumber(string text, List<long> intPart, List<long> decimalPart) {
            ValidateNumber(text);
            bool isPlus = true;
            int haveSym = 0;

            if (text[0] == '-') {
                isPlus = false;
                haveSym = 1;
            } else if (text[0] == '+')
                haveSym = 1;
            int pointIndex = text.IndexOf('.');
            //有小数点
            if (pointIndex != -1) {
                int i = 0;
                if ((pointIndex - haveSym) % BigNumber.OneCount != 0)
                    intPart.Add(Convert.ToInt64(text.Substring(haveSym, (pointIndex - haveSym) % BigNumber.OneCount)));
                for (; i < (pointIndex - haveSym) / BigNumber.OneCount; i++) {
                    intPart.Add(Convert.ToInt64(text.Substring(haveSym + i * BigNumber.OneCount + (pointIndex - haveSym) % BigNumber.OneCount, BigNumber.OneCount)));
                }
                i = pointIndex + 1;
                while (i < text.Length) {
                    if (text.Length - i >= BigNumber.OneCount) {
                        decimalPart.Add(Convert.ToInt64(text.Substring(i, BigNumber.OneCount)));
                    } else {
                        decimalPart.Add(Convert.ToInt64(text.Substring(i, (text.Length - i) % BigNumber.OneCount).PadRight(BigNumber.OneCount, '0')));
                    }
                    i += BigNumber.OneCount;
                }

            }
                //没有小数点
            else {
                if ((text.Length - haveSym) % BigNumber.OneCount != 0)
                    intPart.Add(Convert.ToInt64(text.Substring(haveSym, (text.Length - haveSym) % BigNumber.OneCount)));
                for (int i = 0; i < (text.Length - haveSym) / BigNumber.OneCount; i++) {
                    intPart.Add(Convert.ToInt64(text.Substring(haveSym + i * BigNumber.OneCount + (text.Length - haveSym) % BigNumber.OneCount, BigNumber.OneCount)));
                }

            }
            BigCalculate.RemoveStartZero(intPart);
            if (intPart.Count == 0)
                intPart.Add(0);
            return isPlus;
        }

      public  static void ValidateNumber(string text) {
            Match m = Regex.Match(text, @"[^\d\.\+-]"); //
            if (m.Success)
                throw new NumberException("含有非法字符 :"+text, m.Index);
            Match mNum = Regex.Match(text, @"\d");
            if (!mNum.Success)
                throw new NumberException("至少要含有一个数字:" + text, 0);
            Match mPlug = Regex.Match(text, @"[\+-]", RegexOptions.RightToLeft);
            if (mPlug.Success && mPlug.Index != 0)
                throw new NumberException("正负号只能在开头:" + text, mPlug.Index);
            MatchCollection ms = Regex.Matches(text, @"[\.]");
            if (ms.Count > 1)
                throw new NumberException("不能有一个以上的小数点:" + text, ms[1].Index);
            else if (ms.Count == 1 && (ms[0].Index == 0 || ms[0].Index == text.Length - 1))
                throw new NumberException("小数点不能在开头或最后一位:" + text, ms[0].Index);
            Match mPoints = Regex.Match(text, @"[\+-]\.");
            if (mPoints.Success)
                throw new NumberException("正负号后不能直接有小数点:" + text, mPoints.Index);
        }
        /// <summary>
        /// 模糊幂计算（精度较低，在数量很大时使用效率比较高）
        /// </summary>
        /// <param name="a"></param>
        /// <param name="pow"></param>
        /// <returns></returns>
        public static BigNumber PowDim(BigNumber a, BigNumber pow)
        {
            long powLong = pow.ToLong();
            //Debug.Log(powLong);
            string identityNum = a.ToScientificString(2);
            string[] arr = identityNum.Split('E');
            float head = float.Parse(arr[0]);

            //Debug.Log("identityNum :" + identityNum+"  ARr:"+String.Join(",",arr));
            float minResNum = float.MaxValue / head;
            long toltalPw = 0;
            //Debug.Log("lType :" + lType + "  minResNum:" + minResNum);
            float tempRes = 1;

            for (int i = 0; i < powLong; i++)
            {
                tempRes = tempRes * head;
                //Debug.Log("tempRes:"+tempRes);
                if (tempRes >= minResNum)
                {
                    while (tempRes > 1)
                    {
                        tempRes /= 10;
                        toltalPw++;
                        //Debug.Log(tempRes);
                       
                    }
                    tempRes = 1;
                }
            }
            while (tempRes > 1)
            {
                float temp = tempRes / 10;
                if (temp == 0)
                {
                    tempRes = tempRes % 10;
                    break;
                }
                else
                    tempRes = tempRes / 10;
                toltalPw++;
                //Debug.Log(tempRes);
              
            }

            
            if (arr.Length > 1)
            {
                long pwRes = 1;
                long PwPart = long.Parse(arr[1]);
                if (PwPart > 0)
                {
                    long minPwNum = long.MaxValue / PwPart;
                    for (int i = 0; i < powLong; i++)
                    {
                        pwRes = pwRes * PwPart;
                        //Debug.Log("pwRes :" + pwRes);
                        if (pwRes >= minPwNum)
                        {
                            break;
                        }
                    }
                    toltalPw += pwRes;
                }
                
            }

            if(tempRes<1)
            {
                tempRes = tempRes * 10;
                toltalPw--;
            }
            string resStr = tempRes.ToString("0.0") + "E" ;
            if (toltalPw > 0)
                resStr += "+";
            resStr += toltalPw;
            //Debug.Log("resStr:" + resStr);
            return new BigNumber(resStr);

           // return BigNumber.One;
        }
    } 

  
} // end namespace
